package com.github.cakin.shiro.chapter18.service;

import com.github.cakin.shiro.chapter18.dao.ResourceDao;
import com.github.cakin.shiro.chapter18.entity.Resource;
import org.apache.shiro.authz.permission.WildcardPermission;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @className: ResourceService
 * @description: 资源服务
 * @date: 2020/5/25
 * @author: cakin
 */
@Service
public class ResourceServiceImpl implements ResourceService {
    /**
     * 注入resourceDao
     */
    @Autowired
    private ResourceDao resourceDao;

    /**
     * 功能描述：创建资源
     *
     * @param resource 资源
     * @return Resource 资源
     * @author cakin
     * @date 2020/5/25
     */
    public Resource createResource( Resource resource ) {
        return resourceDao.createResource(resource);
    }

    /**
     * 功能描述：更新资源
     *
     * @param resource 资源
     * @return Resource 资源
     * @author cakin
     * @date 2020/5/25
     */
    public Resource updateResource( Resource resource ) {
        return resourceDao.updateResource(resource);
    }

    /**
     * 功能描述：根据资源Id查找资源
     *
     * @param resourceId 资源Id
     * @author cakin
     * @date 2020/5/25
     */
    public void deleteResource( Long resourceId ) {
        resourceDao.deleteResource(resourceId);
    }

    /**
     * 功能描述：根据资源Id查找资源
     *
     * @param resourceId 资源Id
     * @author cakin
     * @return Resource 资源
     * @date 2020/5/25
     */
    public Resource findOne( Long resourceId ) {
        return resourceDao.findOne(resourceId);
    }

    /**
     * 功能描述：查找所有资源
     *
     * @return List<Resource> 资源列表
     * @author cakin
     * @date 2020/5/25
     */
    public List<Resource> findAll() {
        return resourceDao.findAll();
    }

    /**
     * 得到资源id列表找到对应的权限字符串
     *
     * @param resourceIds 资源Id列表
     * @return Set<String> 资源字符集
     * @author cakin
     * @date 2020/5/25
     */
    public Set<String> findPermissions( Set<Long> resourceIds ) {
        Set<String> permissions = new HashSet<String>();
        for (Long resourceId : resourceIds) {
            Resource resource = findOne(resourceId);
            if (resource != null && !StringUtils.isEmpty(resource.getPermission())) {
                permissions.add(resource.getPermission());
            }
        }
        return permissions;
    }

    /**
     * 根据用户权限得到菜单
     *
     * @param permissions 权限集
     * @return List<Resource> 资源列表
     * @author cakin
     * @date 2020/5/25
     */
    public List<Resource> findMenus( Set<String> permissions ) {
        List<Resource> allResources = findAll();
        List<Resource> menus = new ArrayList<Resource>();
        for (Resource resource : allResources) {
            if (resource.isRootNode()) {
                continue;
            }
            if (resource.getType() != Resource.ResourceType.menu) {
                continue;
            }
            if (!hasPermission(permissions, resource)) {
                continue;
            }
            menus.add(resource);
        }
        return menus;
    }

    private boolean hasPermission( Set<String> permissions, Resource resource ) {
        if (StringUtils.isEmpty(resource.getPermission())) {
            return true;
        }
        for (String permission : permissions) {
            WildcardPermission p1 = new WildcardPermission(permission);
            WildcardPermission p2 = new WildcardPermission(resource.getPermission());
            if (p1.implies(p2) || p2.implies(p1)) {
                return true;
            }
        }
        return false;
    }
}
